package com.easywan.inteceptor;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;

import com.easywan.pojo.PageRow;

@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args = { Connection.class, Integer.class })})
public class PageInterceptor  implements Interceptor{
	private static final DefaultReflectorFactory DEFAULT_REFLECTOR_FACTORY= new DefaultReflectorFactory();
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
		
		Method method = invocation.getMethod();
		Connection connect = (Connection) invocation.getArgs()[0];
		BoundSql boundSql = statementHandler.getBoundSql();
		/**

		 * 获取要运行的sql

		 */
		 MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
		 String selectId=mappedStatement.getId();
		 
		 String sql = boundSql.getSql();
		
		if(!selectId.endsWith("page") && !selectId.endsWith("Page")) return invocation.proceed();
		//System.out.println(sql);

		
		/**

		 * 封装SQL获取数据库长度

		 */
		String sqlTemp = "select count(1) as total from (" + sql+") a";
		PreparedStatement pstmt = connect.prepareStatement(sqlTemp);
		/**

		 * 绑定参数

		 */
		 BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), sqlTemp, boundSql.getParameterMappings(),
                 boundSql.getParameterObject());

         // 从原有BoundSql中获取参数映射，设置到count的BoundSql中，这样就可以在配置文件中使用bind标签

         for (ParameterMapping pm : boundSql.getParameterMappings()) {
             String property = pm.getProperty();
             if (null != property && "" != property) {
                 Object value = boundSql.getAdditionalParameter(property);
                 if (value != null) {
                     countBS.setAdditionalParameter(property, value);
                 }
             }
         }
         ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, countBS.getParameterObject(), boundSql);
         parameterHandler.setParameters(pstmt);
          ResultSet rs = pstmt.executeQuery();
         int totalCount = 0;
         if (rs.next()) {
             totalCount = rs.getInt(1);
         }
         System.out.println(sqlTemp);
         System.out.println(totalCount);
		 
         PageRow pageRow =  (PageRow) metaStatementHandler.getValue("delegate.boundSql.parameterObject."+PageRow.PAGE_CONST);
         
        
         
         if(pageRow == null){
        	 pageRow = new PageRow();
         }
         if(pageRow.getCur() == null){
        	 pageRow.setCur(1L); 
         }
         if(pageRow.getPageSize() == null || pageRow.getPageSize() == 0){
        	 pageRow.setPageSize(10);
         }
         pageRow.setStart((pageRow.getCur() - 1) * pageRow.getPageSize() + 0L);
         /**

          * 拼装分页查询

          */
         pageRow.setTotal(totalCount/pageRow.getPageSize() + ((totalCount%pageRow.getPageSize())==0?0L:1L));
         String limitSql = sql + " limit " + pageRow.getStart() + "," + pageRow.getPageSize();
		//System.out.println(metaStatementHandler.getValue("delegate.boundSql.sql"));

		System.out.println(limitSql);
		
		metaStatementHandler.setValue("delegate.boundSql.sql", limitSql);
		//boudSql.get

		/**

		 * //return invocation.getMethod().invoke(invocation.getTarget(), invocation.getArgs());

		 */
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		/**

		 * 这里会路由到 

		 * org.apache.ibatis.executor.CachingExecutor

		 * org.apache.ibatis.scripting.defaults.DefaultParameterHandler

		 * org.apache.ibatis.executor.resultset.DefaultResultSetHandler

		 * org.apache.ibatis.executor.statement.RoutingStatementHandler

		 * 

		 * 拦截org.apache.ibatis.executor.statement.RoutingStatementHandler

		 */
		System.out.println(target.toString());
		if(target instanceof RoutingStatementHandler){
			/**

			 * 此方法  会获取 目标拦截器的头上的注解

			 */
			target = Plugin.wrap(target, this);
			
		}
		return target;
	}

	@Override
	public void setProperties(Properties arg0) {
		// TODO Auto-generated method stub
		
	}
	
}
